<template>
	<div class="system_menu">
		<!-- 搜索 -->
		<el-form class="search_form" :model="payload" label-width="80px">
			<el-row>
				<el-col :span="6">
					<el-form-item label="菜单名称" prop="menuName">
						<el-input v-model="payload.menuName" placeholder="菜单名称" />
						<el-input v-show="false" />
					</el-form-item>
				</el-col>
				<el-col :span="18" class="search_buttons">
					<el-button type="primary" @click="queryMenusList">搜索</el-button>
					<el-button plain @click="resetPayload">重置</el-button>
				</el-col>
			</el-row>
		</el-form>

		<!-- 表格 -->
		<ContentTable ref="tableRef" v-bind="tableConfig" :data="tableData">
			<template #toolbar>
				<el-button type="primary" @click="openDialog('新建菜单')">新 建</el-button>
			</template>
			<template #menuType="{ row }">
				<span v-if="row.menuType == 0">目录</span>
				<span v-else-if="row.menuType == 1">菜单</span>
			</template>
			<template #status="{ row }">
				<el-tag v-if="row.status == 0">正常</el-tag>
				<el-tag v-else-if="row.status == 1" type="warning">停用</el-tag>
			</template>
			<template #handler="{ row }">
				<el-button type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
				<el-button type="danger" size="small" @click="handleDelete(row)">删除</el-button>
			</template>
		</ContentTable>

		<!-- 新增、编辑 -->
		<el-dialog v-model="open" :title="dialogTitle" width="650" top="10vh" :before-close="handleCancel">
			<el-form ref="formRef" :model="formData" label-width="100px" :rules="rules">
				<el-row>
					<el-col :span="12">
						<el-form-item label="菜单类型" prop="menuType">
							<el-radio-group v-model="formData.menuType" :disabled="Boolean(formData.id)" @change="onMenuTypeChange">
								<el-radio label="0">目录</el-radio>
								<el-radio label="1">菜单</el-radio>
							</el-radio-group>
						</el-form-item>
					</el-col>
					<el-col :span="12">
						<el-form-item label="排序" prop="orderNum">
							<el-input-number v-model="formData.orderNum" :min="0" />
						</el-form-item>
					</el-col>
					<el-col :span="24">
						<el-col :span="18">
							<el-form-item label="上级目录" prop="parentId">
								<el-tree-select
									v-model="formData.parentId"
									style="width: 100%"
									:data="menusTreeOptions"
									check-strictly
									:render-after-expand="false"
								/>
							</el-form-item>
						</el-col>
					</el-col>
					<el-col :span="12">
						<el-form-item :label="labelPrefix + '名称'" prop="menuName">
							<el-input v-model="formData.menuName" :placeholder="'请输入' + labelPrefix + '名称'" />
						</el-form-item>
					</el-col>
					<el-col :span="12">
						<el-form-item v-if="formData.menuType == 0" label="目录图标" prop="icon">
							<el-input v-model="formData.icon" placeholder="请输入element-plus图标名称" />
						</el-form-item>
					</el-col>
					<el-col :span="24">
						<el-form-item label="菜单地址" prop="path">
							<el-input v-model="formData.path" placeholder="请输入菜单地址" />
						</el-form-item>
					</el-col>
					<template v-if="formData.menuType == 1">
						<el-col :span="24">
							<el-form-item label="组件路径" prop="component">
								<el-input v-model="formData.component" placeholder="请输入vue组件路径" />
							</el-form-item>
						</el-col>
						<el-col :span="12">
							<el-form-item label="是否缓存" prop="isCache">
								<el-radio-group v-model="formData.isCache">
									<el-radio :label="0">否</el-radio>
									<el-radio :label="1">是</el-radio>
								</el-radio-group>
							</el-form-item>
						</el-col>
						<el-col :span="12">
							<el-form-item label="是否隐藏" prop="hidden">
								<el-radio-group v-model="formData.hidden">
									<el-radio label="0">否</el-radio>
									<el-radio label="1">是</el-radio>
								</el-radio-group>
							</el-form-item>
						</el-col>
						<el-col :span="12">
							<el-form-item label="是否外链接" prop="isLink">
								<el-radio-group v-model="formData.isLink">
									<el-radio :label="0">否</el-radio>
									<el-radio :label="1">是</el-radio>
								</el-radio-group>
							</el-form-item>
						</el-col>
						<el-col :span="12">
							<el-form-item label="状态" prop="status">
								<el-switch
									v-model="formData.status"
									active-value="0"
									inactive-value="1"
									style="--el-switch-off-color: red"
								/>
							</el-form-item>
						</el-col>
						<el-col v-if="formData.isLink == 1" :span="24">
							<el-form-item label="链接地址" prop="linkUrl">
								<el-input v-model="formData.linkUrl" placeholder="新窗口链接地址" />
							</el-form-item>
						</el-col>
					</template>

					<el-col :span="24">
						<el-form-item label="备注" prop="remark">
							<el-input v-model="formData.remark" type="textarea" rows="3" maxlength="500" show-word-limit />
						</el-form-item>
					</el-col>
				</el-row>
			</el-form>
			<template #footer>
				<el-button type="primary" @click="handleSubmit">确 定</el-button>
				<el-button @click="handleCancel">取 消</el-button>
			</template>
		</el-dialog>
	</div>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import ContentTable from '@/components/ContentTable/ContentTable.vue'
import { tableConfig, rules } from './config'
import { selectMenus, updateMenu, insertMenu, deleteMenu } from '@/service/system/menu'

// 初始化table数据和搜索
const payload = ref<any>({})
const tableRef = ref()
const tableData = ref<any>([])
const copyRowKeys = [
	'id',
	'menuName',
	'menuType',
	'orderNum',
	'parentId',
	'hidden',
	'isCache',
	'isLink',
	'linkUrl',
	'path',
	'component',
	'icon',
	'status',
	'remark'
]
async function queryMenusList() {
	if (tableRef.value) tableRef.value.loading = true
	const result = await selectMenus(payload.value)
	tableData.value = tableTree(result, 0)
}
queryMenusList()
function resetPayload() {
	payload.value = {}
	queryMenusList()
}
function handleEdit(row: any) {
	openDialog('编辑')
	for (const key of copyRowKeys) {
		formData.value[key] = row[key]
	}
}
function handleDelete(row: any) {
	ElMessageBox.confirm('确认删除此数据？', '提示', {
		confirmButtonText: '确认',
		cancelButtonText: '取消',
		type: 'warning'
	})
		.then(async () => {
			await deleteMenu(row.id)
			ElMessage.success('删除成功！')
			queryMenusList()
		})
		.catch(() => {})
}

// 新增菜单
const open = ref(false)
const dialogTitle = ref('')
const formData = ref<any>({ menuType: '0', orderNum: 0, isCache: 0, hidden: '0', isLink: 0, status: '0', parentId: 0 })
const labelPrefix = ref('目录')
const menusTreeOptions = reactive<any>([
	{
		value: 0,
		label: '主目录',
		children: []
	}
])
async function openDialog(title: string) {
	dialogTitle.value = title
	open.value = true
	const result = await selectMenus(null)
	menusTreeOptions[0].children = menusTree(result, 0)
}
function handleCancel() {
	open.value = false
	formData.value = { menuType: '0', orderNum: 0, isCache: 0, hidden: '0', isLink: 0, status: '0', parentId: 0 }
}

function onMenuTypeChange(value: number) {
	if (value == 0) {
		labelPrefix.value = '目录'
	} else if (value == 1) {
		labelPrefix.value = '菜单'
	}
}

// 提交
const formRef = ref()
function handleSubmit() {
	formRef.value.validate(async (valid: Boolean) => {
		if (valid) {
			if (formData.value.id) {
				await updateMenu(formData.value)
				ElMessage.success('编辑成功')
				handleCancel()
				queryMenusList()
			} else {
				await insertMenu(formData.value)
				ElMessage.success('新增成功')
				handleCancel()
				queryMenusList()
			}
		}
	})
}

// ============== 工具函数 ================
function menusTree(menus: any, pid: number): any[] {
	const list: any[] = []
	menus?.forEach((menu: any) => {
		if (menu.parentId === pid && menu.menuType == 0) {
			const children = menusTree(menus, menu.id)
			if (children.length) {
				menu.children = children
			}
			const obj = {
				value: menu.id,
				label: menu.menuName,
				children: menu.children
			}
			if (!obj.children) delete obj.children
			list.push(obj)
		}
	})
	return list
}

function tableTree(menus: any, pid: number): any[] {
	const list: any = []
	menus?.forEach((menu: any) => {
		if (menu.parentId === pid) {
			const children = tableTree(menus, menu.id)
			if (children.length) {
				menu.children = children
			}
			if (!menu.children) delete menu.children
			list.push(menu)
		}
	})
	return list
}
</script>

<style scoped></style>
